/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package edu.pdx.cs.guavadata.query;

import edu.pdx.cs.guavadata.Channel;
import edu.pdx.cs.guavadata.Transform;
import edu.pdx.cs.guavadata.domain.Domain;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 *
 * @author VuTran
 */
public class Intersect extends Operator {

    // Relational algebra intersect operator

    List<Operator> children;
    public String alias;

    public List<Operator> getChildren() {
        return children;
    }

    public void setChildren(List<Operator> children) {
        this.children = children;
    }

    public Intersect(Collection<Operator> operators) {
        children = new ArrayList<Operator>(operators);
        for (Operator o : operators)
            o.parent = this;

        try {
            // Dummy check
            if (this.children.size() <= 0)
                throw new Exception("Need to have at least one table in a intersect operator.");

            // Build list of output columns
            this.exposedColumns = new ArrayList<String>(children.get(0).exposedColumns);
            this.exposedDomains = new ArrayList<Domain>(children.get(0).exposedDomains);

            // Union-compatibility check
            int colCount = this.exposedColumns.size();
            for (int i = 1; i < this.children.size(); i++) {
                // Check column count
                if (colCount != this.children.get(i).exposedColumns.size())
                    throw new Exception("Number of columns between argument 0 and argument " + i + " do not match for intersect operator.");

                // Check domains
                for (int j = 0; j < this.children.get(i).exposedDomains.size(); j++) {
                    if (!this.exposedDomains.get(j).equals(this.children.get(i).exposedDomains.get(j)))
                        throw new Exception("Domains " + this.exposedDomains.get(j).toString() +
                                " and " + this.children.get(i).exposedDomains.get(j).toString() + " do not match for intersect operator.");
                }
            }
        } catch (Exception e) {
            System.err.println("ERROR: " + e.toString());
        }
    }

    public Intersect(Collection<Operator> operators, String alias) {
        this(operators);
        this.alias = alias;
    }

    @Override
    public SqlText visit(Provider qv) {
        return qv.transform(this);
    }

    @Override
    public void visit(Channel c, String table) {
        c.mapAliases(this, table);
    }

    @Override
    public void visit(Transform t, Command c) {
        t.expand(this, c);
    }

    @Override
    public void notifyChange(Operator old, Operator newOp) {
        List<Integer> position = new ArrayList<Integer>();
        for (int i = 0; i < children.size(); i++)
            if (children.get(i) == old) {
                position.add(i);
                newOp.parent = this;
            }

        for (Integer i : position) {
            children.remove(i);
            children.add(i, newOp);
        }
    }

    @Override
    public Operator clone() {
        List<Operator> lo = new ArrayList<Operator>();
        for (Operator o : this.children)
            lo.add(o);
        return new Intersect(lo);
    }

}
